#include "TaskPackNodeItem.h"
#include <QDebug>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QRandomGenerator>

TaskPackNodeItem::TaskPackNodeItem()
{
    setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsMovable);
    connect(selectAdapter(), &SelectAdapter::requestGeometry, this, &TaskPackNodeItem::sendGeometry);
    connect(selectAdapter(), &SelectAdapter::satelliteClicked, this, &TaskPackNodeItem::handleSatelliteClicked);
    connect(selectAdapter(), &SelectAdapter::receiveSelectToken, this, &TaskPackNodeItem::receiveSelectToken);
}

SelectAdapter* TaskPackNodeItem::selectAdapter()
{
    return &_select_adapter;
}

void TaskPackNodeItem::sendGeometry()
{
    emit selectAdapter()->sendGeometry(boundingRect());
}

void TaskPackNodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    emit selectAdapter()->geometryChanged(sceneBoundingRect());
    painter->setBrush(brush());
    if (hasFocus())
    {
        painter->setPen(Qt::DashLine);
    }
    else
    {
        painter->setPen(pen());
    }
    painter->drawRect(boundingRect());
}

void TaskPackNodeItem::handleSatelliteClicked(SatellitePosition p)
{
    switch(p)
    {
    case SatellitePosition::LEFT:
        break;
    case SatellitePosition::TOP:
        break;
    case SatellitePosition::RIGHT:
        appendChildNode();
        break;
    case SatellitePosition::BOTTOM:
        appendSiblingNode();
        break;
    default:
        break;
    }
}

void TaskPackNodeItem::appendChildNode()
{
    this->setBrush(QColor(QRandomGenerator::global()->bounded(0, 255) + 1,
                          QRandomGenerator::global()->bounded(0, 255) + 1,
                          QRandomGenerator::global()->bounded(0, 255) + 1));
    if (scene())
        scene()->update();
}

void TaskPackNodeItem::appendSiblingNode()
{
    qDebug() << "TaskPackNodeItem : appendSiblingNode.";
}

void TaskPackNodeItem::receiveSelectToken()
{
    qDebug() << "TaskPackItem : ReceiveSelectToken()";
    setFocus();
}

void TaskPackNodeItem::focusInEvent(QFocusEvent *event)
{
    emit selectAdapter()->requestSelectToken();
    return QGraphicsRectItem::focusInEvent(event);
}

QVariant TaskPackNodeItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
    if (change == QGraphicsItem::ItemPositionHasChanged)
    {
        emit selectAdapter()->geometryChanged(sceneBoundingRect());
    }
    return QGraphicsRectItem::itemChange(change, value);
}

AppendChildNodeSatelliteItem::AppendChildNodeSatelliteItem()
    : _satellite_adapter(SatellitePosition::RIGHT)
{
    hide();
    setBrush(QBrush(Qt::green));
    setFlags(QGraphicsItem::ItemIsFocusable |
             QGraphicsItem::ItemIsSelectable);
    setRect(0, 0, 20, 20);
    connect(satelliteAdapter(), &SatelliteAdapter::receiveGeometry, this, &AppendChildNodeSatelliteItem::adjustGeometry);
    connect(satelliteAdapter(), &SatelliteAdapter::invisible, this, &AppendChildNodeSatelliteItem::invisible);
}

SatelliteAdapter* AppendChildNodeSatelliteItem::satelliteAdapter()
{
    return &_satellite_adapter;
}

void AppendChildNodeSatelliteItem::adjustGeometry(QRectF geometry)
{
    prepareGeometryChange();
    qreal mid_line = (geometry.top() + geometry.bottom()) / static_cast<qreal>(2.0);
    qreal x = geometry.right() + 10.0;
    qreal y = mid_line - boundingRect().height() / 2.0;
    setPos(x, y);
    if (scene())
        scene()->update();
}

void AppendChildNodeSatelliteItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        emit satelliteAdapter()->clicked(satelliteAdapter()->getSatellitePosition());
    }
    QGraphicsEllipseItem::mousePressEvent(event);
}

void AppendChildNodeSatelliteItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        qDebug() << "Satellite : sendSelectToken";
        emit satelliteAdapter()->sendSelectToken();
        if (scene())
            scene()->update();
    }
    QGraphicsEllipseItem::mouseReleaseEvent(event);
}

QVariant AppendChildNodeSatelliteItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
    if (change == QGraphicsItem::ItemSelectedChange)
    {
    }
    return QGraphicsEllipseItem::itemChange(change, value);
}

void AppendChildNodeSatelliteItem::invisible(bool yes)
{
    if (yes)
        hide();
    else
        show();
}

void AppendChildNodeSatelliteItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setBrush(brush());
    painter->setPen(pen());
    painter->drawEllipse(boundingRect());
}
